home *** CD-ROM | disk | FTP | other *** search
/ InterCD 2000 September / september_2000.iso / intercd / root / ^Linux / cdrecord-1.8.1 / cdrecord / fifo.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-12-28  |  17.2 KB  |  784 lines

  1. /* @(#)fifo.c    1.21 99/12/29 Copyright 1989,1997 J. Schilling */
  2. #ifndef lint
  3. static    char sccsid[] =
  4.     "@(#)fifo.c    1.21 99/12/29 Copyright 1989,1997 J. Schilling";
  5. #endif
  6. /*
  7.  *    A "fifo" that uses shared memory between two processes
  8.  *
  9.  *    The actual code is a mixture of borrowed code from star's fifo.c
  10.  *    and a proposal from Finn Arne Gangstad <finnag@guardian.no>
  11.  *    who had the idea to use a ring buffer to handle average size chunks.
  12.  *
  13.  *    Copyright (c) 1989,1997 J. Schilling
  14.  */
  15. /*
  16.  * This program is free software; you can redistribute it and/or modify
  17.  * it under the terms of the GNU General Public License as published by
  18.  * the Free Software Foundation; either version 2, or (at your option)
  19.  * any later version.
  20.  *
  21.  * This program is distributed in the hope that it will be useful,
  22.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  23.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  24.  * GNU General Public License for more details.
  25.  *
  26.  * You should have received a copy of the GNU General Public License
  27.  * along with this program; see the file COPYING.  If not, write to
  28.  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  29.  */
  30.  
  31. #define    DEBUG
  32. /*#define    XDEBUG*/
  33. #include <mconfig.h>
  34. #if    !defined(HAVE_SMMAP) && !defined(HAVE_USGSHM) && !defined(HAVE_DOSALLOCSHAREDMEM)
  35. #undef    FIFO            /* We cannot have a FIFO on this platform */
  36. #endif
  37. #ifdef    FIFO
  38. #if !defined(USE_MMAP) && !defined(USE_USGSHM)
  39. #define    USE_MMAP
  40. #endif
  41. #ifndef    HAVE_SMMAP
  42. #    undef    USE_MMAP
  43. #    define    USE_USGSHM    /* now SYSV shared memory is the default*/
  44. #endif
  45. #ifdef    USE_MMAP        /* Only want to have one implementation */
  46. #    undef    USE_USGSHM    /* mmap() is preferred            */
  47. #endif
  48.  
  49. #ifdef    HAVE_DOSALLOCSHAREDMEM    /* This is for OS/2 */
  50. #    undef    USE_MMAP
  51. #    undef    USE_USGSHM
  52. #    define    USE_OS2SHM
  53. #endif
  54.  
  55. #include <fctldefs.h>
  56. #include <sys/types.h>
  57. #if defined(HAVE_SMMAP) && defined(USE_MMAP)
  58. #include <sys/mman.h>
  59. #endif
  60. #include <stdio.h>
  61. #include <stdxlib.h>
  62. #include <unixstd.h>
  63. #include <waitdefs.h>
  64. #include <utypes.h>
  65. #include <standard.h>
  66. #include <errno.h>
  67. #include <signal.h>
  68. #include <libport.h>
  69.  
  70. #include "cdrecord.h"
  71.  
  72. #ifdef DEBUG
  73. #ifdef XDEBUG
  74. FILE    *ef;
  75. #define    USDEBUG1    if (debug) {if(s == owner_reader)fprintf(ef, "r");else fprintf(ef, "w");fflush(ef);}
  76. #define    USDEBUG2    if (debug) {if(s == owner_reader)fprintf(ef, "R");else fprintf(ef, "W");fflush(ef);}
  77. #else
  78. #define    USDEBUG1
  79. #define    USDEBUG2
  80. #endif
  81. #define    EDEBUG(a)    if (debug) error a
  82. #else
  83. #define    EDEBUG(a)
  84. #define    USDEBUG1
  85. #define    USDEBUG2
  86. #endif
  87.  
  88. #define palign(x, a)    (((char *)(x)) + ((a) - 1 - (((unsigned)((x)-1))%(a))))
  89.  
  90. typedef enum faio_owner {
  91.     owner_none,
  92.     owner_reader,
  93.     owner_writer,
  94.     owner_faio
  95. } fowner_t;
  96.  
  97. char    *onames[] = {
  98.     "none",
  99.     "reader",
  100.     "writer",
  101.     "faio"
  102. };
  103.  
  104. typedef struct faio {
  105.     int    len;
  106.     volatile fowner_t owner;
  107.     short    fd;
  108.     short    saved_errno;
  109.     char    *bufp;
  110. } faio_t;
  111.  
  112. struct faio_stats {
  113.     long    puts;
  114.     long    gets;
  115.     long    empty;
  116.     long    full;
  117.     long    done;
  118.     long    cont_low;
  119. } *sp;
  120.  
  121. #define    MIN_BUFFERS    3
  122.  
  123. #define    MSECS    1000
  124. #define    SECS    (1000*MSECS)
  125.  
  126. /*
  127.  * Note: WRITER_MAXWAIT & READER_MAXWAIT need to be greater than the SCSI
  128.  * timeout for commands that write to the media. This is currently 200s
  129.  * if we are in SAO mode.
  130.  */
  131. /* microsecond delay between each buffer-ready probe by writing process */
  132. #define    WRITER_DELAY    (20*MSECS)
  133. #define    WRITER_MAXWAIT    (240*SECS)    /* 240 seconds max wait for data */
  134.  
  135. /* microsecond delay between each buffer-ready probe by reading process */
  136. #define    READER_DELAY    (80*MSECS)
  137. #define    READER_MAXWAIT    (240*SECS)    /* 240 seconds max wait for reader */
  138.  
  139. LOCAL    char    *buf;
  140. LOCAL    char    *bufbase;
  141. LOCAL    char    *bufend;
  142. LOCAL    long    buflen;
  143.  
  144. extern    int    debug;
  145. extern    int    lverbose;
  146.  
  147. EXPORT    void    init_fifo    __PR((long));
  148. #ifdef    USE_MMAP
  149. LOCAL    char*    mkshare        __PR((int size));
  150. #endif
  151. #ifdef    USE_USGSHM
  152. LOCAL    char*    mkshm        __PR((int size));
  153. #endif
  154. #ifdef    USE_OS2SHM
  155. LOCAL    char*    mkos2shm    __PR((int size));
  156. #endif
  157.  
  158. EXPORT    BOOL    init_faio    __PR((int tracks, track_t *track, int));
  159. EXPORT    BOOL    await_faio    __PR((void));
  160. EXPORT    void    kill_faio    __PR((void));
  161. EXPORT    int    wait_faio    __PR((void));
  162. LOCAL    void    faio_reader    __PR((int tracks, track_t *track));
  163. LOCAL    void    faio_read_track    __PR((track_t *trackp));
  164. LOCAL    void    faio_wait_on_buffer __PR((faio_t *f, fowner_t s,
  165.                       unsigned long delay,
  166.                       unsigned long max_wait));
  167. LOCAL    int    faio_read_segment __PR((int fd, faio_t *f, int len));
  168. LOCAL    faio_t    *faio_ref    __PR((int n));
  169. EXPORT    int    faio_read_buf    __PR((int f, char *bp, int size));
  170. EXPORT    int    faio_get_buf    __PR((int f, char **bpp, int size));
  171. EXPORT    void    fifo_stats    __PR((void));
  172. EXPORT    int    fifo_percent    __PR((BOOL addone));
  173.  
  174.  
  175. EXPORT void
  176. init_fifo(fs)
  177.     long    fs;
  178. {
  179.     int    pagesize;
  180.  
  181.     if (fs == 0L)
  182.         return;
  183.  
  184. #ifdef    _SC_PAGESIZE
  185.     pagesize = sysconf(_SC_PAGESIZE);
  186. #else
  187.     pagesize = getpagesize();
  188. #endif
  189.     buflen = roundup(fs, pagesize) + pagesize;
  190.     EDEBUG(("fs: %ld buflen: %ld\n", fs, buflen));
  191.  
  192. #if    defined(USE_MMAP)
  193.     buf = mkshare(buflen);
  194. #endif
  195. #if    defined(USE_USGSHM)
  196.     buf = mkshm(buflen);
  197. #endif
  198. #if    defined(USE_OS2SHM)
  199.     buf = mkos2shm(buflen);
  200. #endif
  201.  
  202.     bufbase = buf;
  203.     bufend = buf + buflen;
  204.     EDEBUG(("buf: %X bufend: %X, buflen: %ld\n", buf, bufend, buflen));
  205.     buf = palign(buf, pagesize);
  206.     buflen -= buf - bufbase;
  207.     EDEBUG(("buf: %X bufend: %X, buflen: %ld (align %ld)\n", buf, bufend, buflen, buf - bufbase));
  208.  
  209.     /*
  210.      * Dirty the whole buffer. This can die with various signals if
  211.      * we're trying to lock too much memory
  212.      */
  213.     fillbytes(buf, buflen, '\0');
  214.  
  215. #ifdef    XDEBUG
  216.     if (debug)
  217.         ef = fopen("/tmp/ef", "w");
  218. #endif
  219. }
  220.  
  221. #ifdef    USE_MMAP
  222. LOCAL char *
  223. mkshare(size)
  224.     int    size;
  225. {
  226.     int    f;
  227.     char    *addr;
  228.  
  229. #ifdef    MAP_ANONYMOUS    /* HP/UX */
  230.     f = -1;
  231.     addr = mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, f, 0);
  232. #else
  233.     if ((f = open("/dev/zero", O_RDWR)) < 0)
  234.         comerr("Cannot open '/dev/zero'.\n");
  235.     addr = mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED, f, 0);
  236. #endif
  237.     if (addr == (char *)-1)
  238.         comerr("Cannot get mmap for %d Bytes on /dev/zero.\n", size);
  239.     close(f);
  240.  
  241.     if (debug) errmsgno(EX_BAD, "shared memory segment attached: %x\n", addr);
  242.  
  243.     return (addr);
  244. }
  245. #endif
  246.  
  247. #ifdef    USE_USGSHM
  248. #include <sys/ipc.h>
  249. #include <sys/shm.h>
  250. LOCAL char *
  251. mkshm(size)
  252.     int    size;
  253. {
  254.     int    id;
  255.     char    *addr;
  256.     /*
  257.      * Unfortunately, a declaration of shmat() is missing in old
  258.      * implementations such as AT&T SVr0 and SunOS.
  259.      * We cannot add this definition here because the return-type
  260.      * changed on newer systems.
  261.      *
  262.      * We will get a warning like this:
  263.      *
  264.      * warning: assignment of pointer from integer lacks a cast
  265.      * or
  266.      * warning: illegal combination of pointer and integer, op =
  267.      */
  268. /*    extern    char *shmat();*/
  269.  
  270.     if ((id = shmget(IPC_PRIVATE, size, IPC_CREAT|0600)) == -1)
  271.         comerr("shmget failed\n");
  272.  
  273.     if (debug) errmsgno(EX_BAD, "shared memory segment allocated: %d\n", id);
  274.  
  275.     if ((addr = shmat(id, (char *)0, 0600)) == (char *)-1)
  276.         comerr("shmat failed\n");
  277.  
  278.     if (debug) errmsgno(EX_BAD, "shared memory segment attached: %x\n", addr);
  279.  
  280.     if (shmctl(id, IPC_RMID, 0) < 0)
  281.         comerr("shmctl failed to detach shared memory segment\n");
  282.  
  283. #ifdef    SHM_LOCK
  284.     /*
  285.      * Although SHM_LOCK is standard, it seems that all versions of AIX
  286.      * ommit this definition.
  287.      */
  288.     if (shmctl(id, SHM_LOCK, 0) < 0)
  289.         comerr("shmctl failed to lock shared memory segment\n");
  290. #endif
  291.  
  292.     return (addr);
  293. }
  294. #endif
  295.  
  296. #ifdef    USE_OS2SHM
  297. LOCAL char *
  298. mkos2shm(size)
  299.     int    size;
  300. {
  301.     char    *addr;
  302.  
  303.     /*
  304.      * The OS/2 implementation of shm (using shm.dll) limits the size of one shared
  305.      * memory segment to 0x3fa000 (aprox. 4MBytes). Using OS/2 native API we have
  306.      * no such restriction so I decided to use it allowing fifos of arbitrary size.
  307.          */
  308.     if(DosAllocSharedMem(&addr,NULL,size,0X100L | 0x1L | 0x2L | 0x10L))
  309.         comerr("DosAllocSharedMem() failed\n");
  310.  
  311.     if (debug)
  312.         errmsgno(EX_BAD, "shared memory allocated at address: %x\n", addr);
  313.  
  314.     return (addr);
  315. }
  316. #endif
  317.  
  318. LOCAL    int    faio_buffers;
  319. LOCAL    int    faio_buf_size;
  320. LOCAL    int    buf_idx;
  321. LOCAL    pid_t    faio_pid;
  322. LOCAL    BOOL    faio_didwait;
  323.  
  324. /*#define    faio_ref(n)    (&((faio_t *)buf)[n])*/
  325.  
  326.  
  327. EXPORT BOOL
  328. init_faio(tracks, track, bufsize)
  329.     int    tracks;
  330.     track_t    *track;
  331.     int    bufsize;
  332. {
  333.     int    n;
  334.     faio_t    *f;
  335.     int    pagesize;
  336.     char    *base;
  337.  
  338.     if (buflen == 0L)
  339.         return (FALSE);
  340.  
  341. #ifdef    _SC_PAGESIZE
  342.     pagesize = sysconf(_SC_PAGESIZE);
  343. #else
  344.     pagesize = getpagesize();
  345. #endif
  346.  
  347.     faio_buf_size = bufsize;
  348.     f = (faio_t *)buf;
  349.  
  350.     /*
  351.      * Compute space for buffer headers.
  352.      * Round bufsize up to pagesize to make each FIFO segment
  353.      * properly page aligned.
  354.      */
  355.     bufsize = roundup(bufsize, pagesize);
  356.     faio_buffers = (buflen - sizeof(*sp)) / bufsize;
  357.     EDEBUG(("bufsize: %d buffers: %d hdrsize %d\n", bufsize, faio_buffers, faio_buffers * sizeof(struct faio)));
  358.  
  359.     /*
  360.      * Reduce buffer space by header space.
  361.      */
  362.     n = sizeof(*sp) + faio_buffers * sizeof(struct faio);
  363.     n = roundup(n, pagesize);
  364.     faio_buffers = (buflen-n) / bufsize;
  365.     EDEBUG(("bufsize: %d buffers: %d hdrsize %d\n", bufsize, faio_buffers, faio_buffers * sizeof(struct faio)));
  366.  
  367.     if (faio_buffers < MIN_BUFFERS) {
  368.         errmsgno(EX_BAD,
  369.             "write-buffer too small, minimum is %dk. Disabling.\n",
  370.                         MIN_BUFFERS*bufsize/1024);
  371.         return (FALSE);
  372.     }
  373.  
  374.     if (debug)
  375.         printf("Using %d buffers of %d bytes.\n", faio_buffers, faio_buf_size);
  376.  
  377.     f = (faio_t *)buf;
  378.     base = buf + roundup(sizeof(*sp) + faio_buffers * sizeof(struct faio),
  379.                 pagesize);
  380.  
  381.     for (n = 0; n < faio_buffers; n++, f++, base += bufsize) {
  382.         /* Give all the buffers to the reader process */
  383.         f->owner = owner_writer;
  384.         f->bufp = base;
  385.         f->fd = -1;
  386.     }
  387.     sp = (struct faio_stats *)f;    /* point past headers */
  388.     sp->gets = sp->puts = sp->done = 0L;
  389.  
  390.     faio_pid = fork();
  391.     if (faio_pid < 0)
  392.         comerr("fork(2) failed");
  393.  
  394.     if (faio_pid == 0) {
  395.         /* child process */
  396.         raisepri(1);        /* almost max priority */
  397.  
  398. #ifdef USE_OS2SHM
  399.         DosGetSharedMem(buf,3);    /* PAG_READ|PAG_WRITE */
  400. #endif
  401.         /* Ignoring SIGALRM cures the SCO usleep() bug */
  402. /*        signal(SIGALRM, SIG_IGN);*/
  403.         faio_reader(tracks, track);
  404.         /* NOTREACHED */
  405.     } else {
  406.         faio_didwait = FALSE;
  407.  
  408.         /* close all file-descriptors that only the child will use */
  409.         for (n = 1; n <= tracks; n++)
  410.             close(track[n].f);
  411.     }
  412.  
  413.     return (TRUE);
  414. }
  415.  
  416. EXPORT BOOL
  417. await_faio()
  418. {
  419.     int    n;
  420.     int    lastfd = -1;
  421.     faio_t    *f;
  422.  
  423.     /*
  424.      * Wait until the reader is active and has filled the buffer.
  425.      */
  426.     if (lverbose || debug) {
  427.         printf("Waiting for reader process to fill input buffer ... ");
  428.         flush();
  429.     }
  430.  
  431.     faio_wait_on_buffer(faio_ref(faio_buffers - 1), owner_reader,
  432.                 500*MSECS, 0);
  433.  
  434.     if (lverbose || debug)
  435.         printf("input buffer ready.\n");
  436.  
  437.     sp->empty = sp->full = 0L;    /* set correct stat state */
  438.     sp->cont_low = faio_buffers;    /* set cont to max value  */
  439.  
  440.     f = faio_ref(0);
  441.     for (n = 0; n < faio_buffers; n++, f++) {
  442.         if (f->fd != lastfd &&
  443.             f->fd == STDIN_FILENO && f->len == 0) {
  444.             errmsgno(EX_BAD, "Premature EOF on stdin.\n");
  445.             kill(faio_pid, SIGKILL);
  446.             return (FALSE);
  447.         }
  448.         lastfd = f->fd;
  449.     }
  450.     return (TRUE);
  451. }
  452.  
  453. EXPORT void
  454. kill_faio()
  455. {
  456.     if (faio_pid > 0)
  457.         kill(faio_pid, SIGKILL);
  458. }
  459.  
  460. EXPORT int
  461. wait_faio()
  462. {
  463.     if (faio_pid > 0 && !faio_didwait)
  464.         return (wait(0));
  465.     faio_didwait = TRUE;
  466.     return (0);
  467. }
  468.  
  469. LOCAL void
  470. faio_reader(tracks, track)
  471.     int    tracks;
  472.     track_t    *track;
  473. {
  474.     /* This function should not return, but _exit. */
  475.     int    trackno;
  476.  
  477.     if (debug)
  478.         printf("\nfaio_reader starting\n");
  479.  
  480.     for (trackno = 1; trackno <= tracks; trackno++) {
  481.         if (debug)
  482.             printf("\nfaio_reader reading track %d\n", trackno);
  483.         faio_read_track(&track[trackno]);
  484.     }
  485.     sp->done++;
  486.     if (debug)
  487.         printf("\nfaio_reader all tracks read, exiting\n");
  488.  
  489.     /* Prevent hang if buffer is larger than all the tracks combined */
  490.     if (sp->gets == 0)
  491.         faio_ref(faio_buffers - 1)->owner = owner_reader;
  492.  
  493. #ifdef    USE_OS2SHM
  494.     DosFreeMem(buf);
  495.     sleep(30000);    /* XXX If calling _exit() here the parent process seems to be blocked */
  496.             /* XXX This should be fixed soon */
  497. #endif
  498.     if (debug)
  499.         error("\nfaio_reader _exit(0)\n");
  500.     _exit(0);
  501. }
  502.  
  503. #ifndef    faio_ref
  504. LOCAL faio_t *
  505. faio_ref(n)
  506.     int    n;
  507. {
  508.     return (&((faio_t *)buf)[n]);
  509. }
  510. #endif
  511.  
  512.  
  513. LOCAL void
  514. faio_read_track(trackp)
  515.     track_t *trackp;
  516. {
  517.     int    fd = trackp->f;
  518.     int    bytespt = trackp->secsize * trackp->secspt;
  519.     int    l;
  520.     long    tracksize = trackp->tracksize;
  521.     long    bytes_read = 0L;
  522.     long    bytes_to_read;
  523.  
  524.     if (bytespt > faio_buf_size) {
  525.         comerrno(EX_BAD,
  526.         "faio_read_track fatal: secsize %d secspt %d, bytespt(%d) > %d !!\n",
  527.              trackp->secsize, trackp->secspt, bytespt,
  528.              faio_buf_size);
  529.     }
  530.  
  531.     do {
  532.         bytes_to_read = bytespt;
  533.         if (tracksize > 0) {
  534.             bytes_to_read = tracksize - bytes_read;
  535.             if (bytes_to_read > bytespt)
  536.                 bytes_to_read = bytespt;
  537.         }
  538.         l = faio_read_segment(fd, faio_ref(buf_idx), bytes_to_read);
  539.         if (++buf_idx >= faio_buffers)
  540.             buf_idx = 0;
  541.         if (l <= 0)
  542.             break;
  543.         bytes_read += l;
  544.     } while (tracksize < 0 || bytes_read < tracksize);
  545.  
  546.     close(fd);    /* Don't keep files open longer than neccesary */
  547. }
  548.  
  549. LOCAL void
  550. faio_wait_on_buffer(f, s, delay, max_wait)
  551.     faio_t    *f;
  552.     fowner_t s;
  553.     unsigned long delay;
  554.     unsigned long max_wait;
  555. {
  556.     unsigned long max_loops;
  557.  
  558.     if (f->owner == s)
  559.         return;        /* return immediately if the buffer is ours */
  560.  
  561.     if (s == owner_reader)
  562.         sp->empty++;
  563.     else
  564.         sp->full++;
  565.  
  566.     max_loops = max_wait / delay + 1;
  567.  
  568.     while (max_wait == 0 || max_loops--) {
  569.         USDEBUG1;
  570.         usleep(delay);
  571.         USDEBUG2;
  572.  
  573.         if (f->owner == s)
  574.             return;
  575.     }
  576.     if (debug) {
  577.         errmsgno(EX_BAD,
  578.         "%lu microseconds passed waiting for %d current: %d idx: %d\n",
  579.         max_wait, s, f->owner, (f - faio_ref(0))/sizeof(*f));
  580.     }
  581.     comerrno(EX_BAD, "faio_wait_on_buffer for %s timed out.\n",
  582.     (s > owner_faio || s < owner_none) ? "bad_owner" : onames[s]);
  583. }
  584.  
  585. LOCAL int
  586. faio_read_segment(fd, f, len)
  587.     int    fd;
  588.     faio_t    *f;
  589.     int    len;
  590. {
  591.     int l;
  592.  
  593.     faio_wait_on_buffer(f, owner_writer, WRITER_DELAY, WRITER_MAXWAIT);
  594.  
  595.     f->fd = fd;
  596.     l = read_buf(fd, f->bufp, len);
  597.     f->len = l;
  598.     f->saved_errno = errno;
  599.     f->owner = owner_reader;
  600.  
  601.     sp->puts++;
  602.  
  603.     return l;
  604. }
  605.  
  606. EXPORT int
  607. faio_read_buf(fd, bp, size)
  608.     int fd;
  609.     char *bp;
  610.     int size;
  611. {
  612.     char *bufp;
  613.  
  614.     int len = faio_get_buf(fd, &bufp, size);
  615.     if (len > 0) {
  616.         movebytes(bufp, bp, len);
  617.     }
  618.     return len;
  619. }
  620.  
  621. EXPORT int
  622. faio_get_buf(fd, bpp, size)
  623.     int fd;
  624.     char **bpp;
  625.     int size;
  626. {
  627.     faio_t    *f;
  628.     int    len;
  629.  
  630. again:
  631.     f = faio_ref(buf_idx);
  632.     if (f->owner == owner_faio) {
  633.         f->owner = owner_writer;
  634.         if (++buf_idx >= faio_buffers)
  635.             buf_idx = 0;
  636.         f = faio_ref(buf_idx);
  637.     }
  638.  
  639.     if ((sp->puts - sp->gets) < sp->cont_low && sp->done == 0) {
  640.         EDEBUG(("gets: %d puts: %d cont: %d low: %d\n", sp->gets, sp->puts, sp->puts - sp->gets, sp->cont_low));
  641.         sp->cont_low = sp->puts - sp->gets;
  642.     }
  643.     faio_wait_on_buffer(f, owner_reader, READER_DELAY, READER_MAXWAIT);
  644.     len = f->len;
  645.     
  646.     if (f->fd != fd) {
  647.         if (f->len == 0) {
  648.             /*
  649.              * If the tracksize for this track was known, and
  650.              * the tracksize is 0 mod bytespt, this happens.
  651.              */
  652.             goto again;
  653.         }
  654.         comerrno(EX_BAD,
  655.         "faio_get_buf fatal: fd=%d, f->fd=%d, f->len=%d f->errno=%d\n",
  656.         fd, f->fd, f->len, f->saved_errno);
  657.     }
  658.     if (size < len) {
  659.         comerrno(EX_BAD,
  660.         "unexpected short read-attempt in faio_get_buf. size = %d, len = %d\n",
  661.         size, len);
  662.     }
  663.  
  664.     if (len < 0)
  665.         errno = f->saved_errno;
  666.  
  667.     sp->gets++;
  668.  
  669.     *bpp = f->bufp;
  670.     f->owner = owner_faio;
  671.     return len;
  672. }
  673.  
  674. EXPORT void
  675. fifo_stats()
  676. {
  677.     if (sp == NULL)    /* We might not use a FIFO */
  678.         return;
  679.  
  680.     errmsgno(EX_BAD, "fifo had %ld puts and %ld gets.\n",
  681.         sp->puts, sp->gets);
  682.     errmsgno(EX_BAD, "fifo was %ld times empty and %ld times full, min fill was %ld%%.\n",
  683.         sp->empty, sp->full, (100L*sp->cont_low)/faio_buffers);
  684. }
  685.  
  686. EXPORT int
  687. fifo_percent(addone)
  688.     BOOL    addone;
  689. {
  690.     int    percent;
  691.  
  692.     if (buflen == 0L)
  693.         return (-1);
  694.     if (sp->done)
  695.         return (100);
  696.     percent = (100*(sp->puts + 1 - sp->gets)/faio_buffers);
  697.     if (percent > 100)
  698.         return (100);
  699.     return (percent);
  700. }
  701. #else    /* FIFO */
  702.  
  703. #include <standard.h>
  704. #include <sys/types.h>
  705. #include <utypes.h>
  706.  
  707. #include "cdrecord.h"
  708.  
  709. EXPORT    void    init_fifo    __PR((long));
  710. EXPORT    BOOL    init_faio    __PR((int tracks, track_t *track, int));
  711. EXPORT    BOOL    await_faio    __PR((void));
  712. EXPORT    void    kill_faio    __PR((void));
  713. EXPORT    int    wait_faio    __PR((void));
  714. EXPORT    int    faio_read_buf    __PR((int f, char *bp, int size));
  715. EXPORT    int    faio_get_buf    __PR((int f, char **bpp, int size));
  716. EXPORT    void    fifo_stats    __PR((void));
  717. EXPORT    int    fifo_percent    __PR((BOOL addone));
  718.  
  719.  
  720. EXPORT void
  721. init_fifo(fs)
  722.     long    fs;
  723. {
  724.     errmsgno(EX_BAD, "Fifo not supported.\n");
  725. }
  726.  
  727. EXPORT BOOL
  728. init_faio(tracks, track, bufsize)
  729.     int    tracks;
  730.     track_t    *track;
  731.     int    bufsize;
  732. {
  733.     return (FALSE);
  734. }
  735.  
  736. EXPORT BOOL
  737. await_faio()
  738. {
  739.     return (TRUE);
  740. }
  741.  
  742. EXPORT void
  743. kill_faio()
  744. {
  745. }
  746.  
  747. EXPORT int
  748. wait_faio()
  749. {
  750.     return (0);
  751. }
  752.  
  753. EXPORT int
  754. faio_read_buf(fd, bp, size)
  755.     int fd;
  756.     char *bp;
  757.     int size;
  758. {
  759.     return (0);
  760. }
  761.  
  762. EXPORT int
  763. faio_get_buf(fd, bpp, size)
  764.     int fd;
  765.     char **bpp;
  766.     int size;
  767. {
  768.     return (0);
  769. }
  770.  
  771. EXPORT void
  772. fifo_stats()
  773. {
  774. }
  775.  
  776. EXPORT int
  777. fifo_percent(addone)
  778.     BOOL    addone;
  779. {
  780.     return (-1);
  781. }
  782.  
  783. #endif    /* FIFO */
  784.